package com.liushuai.loadbalancer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Random;

/**
 * @author ：liushuai
 * @date ：Created in 2020/11/5 16:50
 * @description：${description}
 * @modified By：
 * @version: $version$
 */
@RestController
@SpringBootApplication
@Slf4j
public class LoadBalancerDemoApplication {

    private final WebClient.Builder loadBalancedWebClientBuilder;
    private final ReactorLoadBalancerExchangeFilterFunction lbFunction;

    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    RestTemplate restTemplate;

    public LoadBalancerDemoApplication(WebClient.Builder webClientBuilder,
                                       ReactorLoadBalancerExchangeFilterFunction lbFunction) {
        this.loadBalancedWebClientBuilder = webClientBuilder;
        this.lbFunction = lbFunction;
    }

    public static void main(String[] args) {
        SpringApplication.run(LoadBalancerDemoApplication.class, args);
    }

    @RequestMapping("/hi")
    public Mono<String> hi(@RequestParam(value = "name", defaultValue = "Mary") String name) {
        return loadBalancedWebClientBuilder.build().get().uri("http://say-hello/app/greeting")
                .retrieve().bodyToMono(String.class)
                .map(greeting -> String.format("%s, %s!", greeting, name));
    }

    @RequestMapping("/hello")
    public Mono<String> hello(@RequestParam(value = "name", defaultValue = "John") String name) {
        return WebClient.builder().filter(lbFunction).build().get().uri("http://say-hello/app/greeting").retrieve().bodyToMono(String.class)
                .map(greeting -> String.format("%s, %s!", greeting, name));
    }

    @RequestMapping("/hi2")
    public String hi2(@RequestParam(value = "name", defaultValue = "Mary") String name) {
        return "";
    }

    /**
     * 从nacos获取服务地址端口，然后访问
     * 没有使用负载均衡算法，写了一个随机数，取ip
     * @param name
     * @return
     */
    @RequestMapping("/hello2")
    public String hello2(@RequestParam(value = "name", defaultValue = "John") String name) {
        //不包括nacos的权重设置为0的注册服务
        List<ServiceInstance> instanceList=discoveryClient.getInstances("app");
        //设置随机数范围，即为注册服务的个数
        ServiceInstance instance=instanceList.get(new Random().nextInt(instanceList.size()));
        String url = String.format("http://%s:%s/app/greeting", instance.getHost(),instance.getPort());
        String rsp = restTemplate().getForObject(url, String.class);
        return rsp;
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}
